#include "GL/glew.h"
#include "LoadShader.h"
#include "3Dmodel/Panel.h"
#include "utility.h"
#include "vmath.h"

extern int Width, Height;


GLuint program, vao, vbo;
GLfloat vert[] = 
{
	 0.0f,  0.8f, 1.0f, 0.0f, 0.0f,
    -0.8f, -0.8f, 0.0f, 1.0f, 0.0f,
     0.8f, -0.8f, 0.0f, 0.0f, 1.0f };

GLuint frameBuffer[7]{ 0 };//1- cube, 2-texture2D
GLuint tex[2]{ 0 };
const GLuint Texsize = 200;
const GLuint FrameBufferCount = sizeof(frameBuffer)/sizeof(frameBuffer[0]);

GLuint program2D, programCube;
Model3D panel;

bool init()
{
	ShaderInfo si[] = { { GL_VERTEX_SHADER, "Shader.vert" },{ GL_FRAGMENT_SHADER, "Shader.frag" },{ GL_NONE, nullptr } };
	program = LoadShade(si);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vert), vert, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, OFFSET_POINTER(sizeof(GLfloat)*2));
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	
	glGenFramebuffers(FrameBufferCount, frameBuffer);
	glGenTextures(2, tex);

	glBindTexture(GL_TEXTURE_2D, tex[0]);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Texsize, Texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer[0]);
	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBindTexture(GL_TEXTURE_CUBE_MAP, tex[1]);
	for (int i = 0; i<6; ++i)
	{
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGBA8, Texsize, Texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer[i+1]);
		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, tex[1], 0);
	}

	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

	ShaderInfo si2[] = { { GL_VERTEX_SHADER, "Texture2D.vert" },{ GL_FRAGMENT_SHADER, "Texture2D.frag" },{ GL_NONE, nullptr } };
	program2D = LoadShade(si2);

	ShaderInfo si3[] = { { GL_VERTEX_SHADER, "Cube.vert" },{ GL_FRAGMENT_SHADER, "Cube.frag" },{ GL_NONE, nullptr } };
	programCube = LoadShade(si3);

	panel = LoadPanel(0, -1, 1);

	return true;
}

void Display(double time)
{
	GLint oldViewPort[4]{ 0 };
	glGetIntegerv(GL_VIEWPORT, oldViewPort);

	for (int i = 0; i< FrameBufferCount; ++i) //1-2D, 2-Cube
	{
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer[i]);
		glViewport(0, 0, Texsize, Texsize);
		glClearColor(0.2f, 0.05f*i, 0.45f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glUseProgram(program);
		glBindVertexArray(vao);
		glDrawArrays(GL_TRIANGLES, 0, 3);
	}

	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
	glViewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]);
	glClearColor(0.0f, 0.05f, 0.05f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	glUseProgram(program2D);
	auto m = Matrix4f::createScale(0.003f, 0.003f*Width / Height, 0.0f);
	m = Matrix4f::createTranslation(-0.5f, 0.f, 0.f) * m;
	glUniformMatrix4fv(0, 1, GL_FALSE, m);
	glUniform1i(1, 0);
	glBindTexture(GL_TEXTURE_2D, tex[0]);
	panel.Draw();
	glBindTexture(GL_TEXTURE_2D, 0);

	glUseProgram(programCube);
	m = Matrix4f::createTranslation(1.0f, 0.f, 0.f) * m;
	glUniformMatrix4fv(0, 1, GL_FALSE, m);
	glUniform1i(1, 0);
	glBindTexture(GL_TEXTURE_CUBE_MAP, tex[1]);
	panel.Draw();
	glBindTexture(GL_TEXTURE_CUBE_MAP, 0);


}

void onClose()
{
	glDeleteVertexArrays(1, &vao);
	glDeleteBuffers(1, &vbo);
}


